/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package view;

/**
 * A hálózat megjelenítésével kapcsolatos feladatokért felelős osztály.
 * Listát tart nyilván a grafikus alkatrészosztályokról,
 * biztosítja ezekhez a listákhoz a kezelőfüggvényeket.
 * Felelős a hálózat kirajzolásáért,
 * valamint az egérrel a rajzterületre való kattintás lekezeléséért.
 * @author Gergő
 */
import controller.*;
import java.util.HashMap;
import java.util.Collection;
import java.util.Iterator;
import java.awt.Point;
import java.awt.Graphics;
import java.util.Vector;

public class View {

    /**
    * A VisualElement referenciákat tároló Vector típusú adatstruktúra.
    */
    Vector<VisualElement> VisualElementList;
    /**
    * A VisualWire referenciákat tároló Vector típusú adatstruktúra.
    */
    Vector<VisualWire> VisualWireList;
    /**
    * Azokat a VisuaElement referenciákat tárolja, melyek leszármaznak a
    * ClickAble osztályból, avagy lehet rájuk kattintani.
    */
    HashMap<Integer, Clickable> ClickableList;

    /**
    * A View konstruktora. Létrehozza a listákat és beállítja a VisualElement
    * statikus controller változóját a setController függvényének meghívásával.
    * @param controller A Controller referenciája.
    */
    public View (Controller controller)
    {
        VisualElementList=new Vector<VisualElement>();
        VisualWireList=new Vector<VisualWire>();
        ClickableList=new HashMap<Integer, Clickable>();
        VisualElement.setController(controller);
    }

    /**
    * A VisualElementek kapott értékekkel való létrehozását és megfelelő listához adását végző függvény.
    * @param id     A létrehozandó objektum ID-je. Továbbadandó.
    * @param pos    A létrehozandó objektum pozíciója. Továbbadandó.
    * @param type   Ez alapján dönti el a létrehozandó elem fajtáját.
    * @param in     A létrehozandó objektum bemeneteinek száma. Továbbadandó.
    * @param out    A létrehozandó objektum kimeneteinek száma. Továbbadandó.
    */
    public void addVisualElement(int id,Point pos,String type,int in,int out) throws IllegalArgumentException
    {
        try {
                if (type.compareTo("and") == 0){
                    VisualAnd newelem = new VisualAnd(id,pos,"and",in,out);
                    if (VisualElementList.size() <= id) VisualElementList.setSize(id+1);
                    VisualElementList.set(id, newelem);
                }
                else if(type.compareTo("or") == 0){
                    VisualOr newelem = new VisualOr(id,pos,"or",in,out);
                    if (VisualElementList.size() <= id) VisualElementList.setSize(id+1);
                    VisualElementList.set(id, newelem);
                }
                else if(type.compareTo("inverter") == 0){
                    VisualInverter newelem = new VisualInverter(id,pos,"inverter",in,out);
                    if (VisualElementList.size() <= id) VisualElementList.setSize(id+1);
                    VisualElementList.set(id, newelem);
                }
                else if(type.compareTo("led") == 0){
                    VisualLed newelem = new VisualLed(id,pos,"led",in,out);
                    if (VisualElementList.size() <= id) VisualElementList.setSize(id+1);
                    VisualElementList.set(id, newelem);
                }
                else if(type.compareTo("generator") == 0){
                    VisualGenerator newelem = new VisualGenerator(id,pos,"generator",in,out);
                    if (VisualElementList.size() <= id) VisualElementList.setSize(id+1);
                    VisualElementList.set(id, newelem);
                    ClickableList.put(id,newelem);
                }
                else if(type.compareTo("switch") == 0){
                    VisualSwitch newelem = new VisualSwitch(id,pos,"switch",in,out);
                    if (VisualElementList.size() <= id) VisualElementList.setSize(id+1);
                    VisualElementList.set(id, newelem);
                    ClickableList.put(id,newelem);
                }
                else if(type.compareTo("oscilloscope") == 0){
                    VisualOscilloscope newelem = new VisualOscilloscope(id,pos,"oscilloscope",in,out);
                    if (VisualElementList.size() <= id) VisualElementList.setSize(id+1);
                    VisualElementList.set(id, newelem);
                    ClickableList.put(id,newelem);
                }

                else if(type.substring(0, 9).compareTo("composite") == 0){
                    VisualCompositeElement newelem = new VisualCompositeElement(id,pos,type.substring(10),in,out);
                    if (VisualElementList.size() <= id) VisualElementList.setSize(id+1);
                    VisualElementList.set(id, newelem);
                } //ez így még nem teljesen jó, mert nem adtuk át a nevét sehol
                else throw new IllegalArgumentException("Ismeretlen elem: " + type);
            }
            catch (IllegalArgumentException e){
                throw e;
            }
    }

    /**
    * A VisualWire-ök kapott értékekkel való létrehozását és megfelelő listához adását végző függvény.
    * @param ID     A létrehozandó objektum ID-je. Továbbadandó.
    * @param breakpoints    A létrehozandó vezeték töréspontjait tároló 2 dimenziós tömb. Továbbadandó.
    */
    public void addVisualWire(int ID, Point[][] breakpoints) 
    {
        VisualWire newwire = new VisualWire(ID, breakpoints);
        if (VisualWireList.size() <= ID) VisualWireList.setSize(ID+1);
        VisualWireList.set(ID, newwire);
    }

    /**
    * A hálózat kirajzolásáért felelős függvény.
    * @param g     A kirajzoláshoz szükséges Graphics objektum.
    */
    public void drawNetwork(Graphics g)
    {
        for (VisualElement element : VisualElementList) element.draw(g);
        for (VisualWire wire: VisualWireList) wire.draw(g);
    }

    /**
    * Meghívja a kapott ID-jű VisualElement getInputPos függvényét a wire paraméterrel.
    * @param ID     A VisualElementet azonosítja, akinek a függvényét meg kell hívni.
    * @param wire    A bemeneti vezeték sorszáma, aminek a csatlakozási pontját akarjuk. Továbbadandó.
    * @return   Visszaadja a VisualElement függvénye által visszaadott értéket, avagy a csatlakozási pontot.
    * @throws IllegalArgumentException Nem létező VisualElement.
    */
    public Point getInputPos(int ID, int wire) throws IllegalArgumentException
    {
        if(VisualElementList.size()>ID)
        {
            Point temp;
            temp=VisualElementList.get(ID).getInputPos(wire);
            return temp;
        }
        else throw new IllegalArgumentException("A(z) " + Integer.toString(ID) + ". ID-vel nem létezik grafikus elem.");
    }

    /**
    * Meghívja a kapott ID-jű VisualElement getOutputPos függvényét a wire paraméterrel.
    * @param ID     A VisualElementet azonosítja, akinek a függvényét meg kell hívni.
    * @param wire    A kimeneti vezeték sorszáma, aminek a csatlakozási pontját akarjuk. Továbbadandó.
    * @return   Visszaadja a VisualElement függvénye által visszaadott értéket, avagy a csatlakozási pontot.
    * @throws IllegalArgumentException Nem létező VisualElement.
    */
    public Point getOutputPos(int ID, int wire) throws IllegalArgumentException
    {
    if(VisualElementList.size()>ID)
        {
            Point temp;
            temp=VisualElementList.get(ID).getOutputPos(wire);
            return temp;
        }
        else throw new IllegalArgumentException("A(z) " + Integer.toString(ID) + ". ID-vel nem létezik grafikus elem.");
    }

    /**
    * Megkeresi a ClickableList listában azt az objektumot, amire a felhasználó kattintott (amennyiben
    * ClickAble objektumra kattintott) a Clickable objektumok isThere függvényének segítségével.
    * @param pos     A pont koordinátái, ahova a kattintás történt.
    * @return   Visszaadja azt a Clicablet, amire kattintottak.
    */
    public Clickable getClickedObject (Point pos)
    {
        Clickable temp=null;
        Clickable clicked=null;
        Collection<Clickable> c2 = ClickableList.values();
        Iterator<Clickable> iter2 = c2.iterator();
        while (iter2.hasNext()){
            temp=iter2.next();
            if(temp.isThere(pos.x,pos.y)) clicked=temp;
        }
        return clicked;
    }

    /**
    * Meghívja a kapott ID-jű VisualWire setStartingPoint függvényét a point paraméterrel.
    * @param ID     A VisualWiret azonosítja, akinek a függvényét meg kell hívni.
    * @param point    A csatlakozási pont, ahonnan a vezeték indul. Továbbadandó.
    * @throws IllegalArgumentException Nem létező VisualWire.
    */
    public void setStartingPoint(int ID, Point point) throws IllegalArgumentException
    {
        if (VisualWireList.size() > ID)
        {
            VisualWireList.get(ID).setStartingPoint(point);
        }
        else throw new IllegalArgumentException("A(z) " + Integer.toString(ID) + ". ID-vel nem létezik grafikus elem.");
    }

    /**
    * Meghívja a kapott ID-jű VisualWire setEndPoint függvényét a point paraméterrel.
    * @param ID     A VisualWiret azonosítja, akinek a függvényét meg kell hívni.
    * @param point    A csatlakozási pont, ahol a vezeték végződik. Továbbadandó.
    * @param branch     Az ág aminek ez a végpontja. Továbbadandó.
    * @throws IllegalArgumentException Nem létező VisualWire.
    */
    public void setEndPoint (int ID, Point point, int branch) throws IllegalArgumentException
    {
       if (VisualWireList.size() > ID)
        {
            VisualWireList.get(ID).setEndPoint(point,branch);
        }
        else throw new IllegalArgumentException("A(z) " + Integer.toString(ID) + ". ID-vel nem létezik grafikus elem.");

    }
}
